package com.bsoft.gol.hcs.specialist.service.impl;

import com.alibaba.excel.util.DateUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bsoft.gol.hcs.his.bean.request.DeptLeaderListRequest;
import com.bsoft.gol.hcs.his.bean.response.DeptLeaderListRepHisBean;
import ctd.controller.exception.ControllerException;
import ctd.spring.boot.annotation.SsdevService;
import ctd.util.annotation.RpcService;
import com.bsoft.gol.hcs.enumcase.*;
import com.bsoft.gol.hcs.followup.dao.FusAfterHosRecordDAO;
import hcn.base.Doctor;
import hcn.base.Organization;
import hcn.base.notification.event.NotificationEvent;
import hcn.bean.PushMessageBean;
import hcn.enums.MsgTemplateCode;
import hcn.service.base.qo.DoctorListByMemQo;
import hcn.util.BaseResponse;
import hcn.util.ResultCode;
import com.bsoft.gol.hcs.his.bean.request.SearchDocumentRequest;
import com.bsoft.gol.hcs.his.bean.response.QueryPatientInfoResponse;
import com.bsoft.gol.hcs.his.bean.response.SearchDocumentList;
import com.bsoft.gol.hcs.his.bean.response.SearchDocumentResponse;
import com.bsoft.gol.hcs.his.service.IPatientHisService;
import com.bsoft.gol.hcs.his.service.SendMsgService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AliasFor;
import org.springframework.util.CollectionUtils;
import pcn.sign.MpiDemographicinfo;
import service.rpc.DoctorInfoServiceIntf;
import service.rpc.impl.OrganizationRpcServiceImpl;
import service.rpc.impl.PcnIdentityServiceImpl;
import com.bsoft.gol.hcs.specialist.bean.request.PatientSearchRuleRequest;
import com.bsoft.gol.hcs.specialist.bean.response.PatientSearchProcess;
import com.bsoft.gol.hcs.specialist.bean.response.QueryPatientSearchResultResponse;
import com.bsoft.gol.hcs.specialist.bean.vo.PatientSearchResultListVo;
import com.bsoft.gol.hcs.specialist.dao.*;
import com.bsoft.gol.hcs.specialist.entity.*;
import com.bsoft.gol.hcs.specialist.service.IPatientSearchRuleExecuteService;
import com.bsoft.gol.hcs.utils.CommonUtils;
import com.bsoft.gol.hcs.utils.DateUtil;
import com.bsoft.gol.hcs.utils.ThreadPoolExecutorUtil;
import com.bsoft.gol.hcs.visitrecord.dao.VrInpatientVisitRecordDAO;
import com.bsoft.gol.hcs.visitrecord.dao.VrOutpatientVisitRecordDAO;
import com.bsoft.gol.hcs.visitrecord.dao.VrSurgicalRecordDAO;

import java.util.*;
import java.util.stream.Collectors;

import static com.bsoft.gol.hcs.enumcase.RuleConditionTypeEnum.RECORD_TIME;
import static com.bsoft.gol.hcs.enumcase.RuleConditionTypeEnum.getEnumByKey;

/**
 * @author tongtp
 * @version v0.1
 * @package specialist.service.impl
 * @className PatientSearchRuleExecuteServiceImpl
 * @description 患者检索规则执行服务
 * @create 2021-08-06 14:19
 **/
@SsdevService(id= "patientSearchRuleExecute", name= "patientSearchRuleExecuteService")
public class PatientSearchRuleExecuteServiceImpl implements IPatientSearchRuleExecuteService {

    private final static Logger log = LoggerFactory.getLogger(PatientSearchRuleExecuteServiceImpl.class);

    @Autowired
    private PatientSearchRuleDAO patientSearchRuleDAO;
    @Autowired
    private PatientSearchRuleDetailDAO patientSearchRuleDetailDAO;
    @Autowired
    private PatientSearchResultDAO patientSearchResultDAO;
    @Autowired
    private IPatientHisService patientHisService;
    @Autowired
    private InspectReportRecordDAO inspectReportRecordDAO;
    @Autowired
    private ExamReportDAO examReportDAO;
    @Autowired
    private TreatmentRecordDAO treatmentRecordDAO;
    @Autowired
    private VrSurgicalRecordDAO vrSurgicalRecordDAO;
    @Autowired
    private PcnIdentityServiceImpl pcnIdentityServiceImpl;
    @Autowired
    private OrganizationRpcServiceImpl organizationRpcService;
    @Autowired
    private SendMsgService sendMsgService;
    @Autowired
    private FusAfterHosRecordDAO fusAfterHosRecordDAO;
    @Autowired
    private FusAfterHealthEducationDAO fusAfterHealthEducationDAO;
    @Autowired
    private VrOutpatientVisitRecordDAO vrOutpatientVisitRecordDAO;
    @Autowired
    private VrInpatientVisitRecordDAO vrInpatientVisitRecordDAO;
    @Autowired
    private DoctorInfoServiceIntf doctorInfoServiceIntf;

    /**
     * 处理订阅的患者检索规则
     *
     * @return org.atag.core.base.BaseResponse
     * @throws
     * @author tongtp
     * @date 2021/8/10 21:24
     */
    @Override
    @RpcService
    public void handlePatientSearchRuleForSubscribe() throws ControllerException {
        List<PatientSearchRule> patientSearchRules =
                patientSearchRuleDAO.findPatientSearchRuleForSubscribe();
        if (!CollectionUtils.isEmpty(patientSearchRules)) {
            for (PatientSearchRule patientSearchRule : patientSearchRules) {
                ruleExecute(patientSearchRule.getPatientSearchRuleId(), ExecutionModeEnum.SUBSCRIBE.getModeCode(), null);
            }
        }
        return;
    }

    /**
     * 患者检索规则执行检索
     *
     * @param patientSearchRuleId
     * @return org.atag.core.base.BaseResponse
     * @throws
     * @author tongtp
     * @date 2021/8/6 14:18
     */
    @Override
    @RpcService
    public void doSearch(Long patientSearchRuleId) throws ControllerException {
        if (CommonUtils.isEmpty(patientSearchRuleId)) {
            throw new ControllerException("检索规则id不可为空");
        }
        this.ruleExecute(patientSearchRuleId, ExecutionModeEnum.SEARCH.getModeCode(), null);
    }

    /**
     * 刷新已订阅的规则病例数
     *
     * @param request
     * @return org.atag.core.base.BaseResponse
     * @throws
     * @author tongtp
     * @date 2021/8/11 11:23
     */
    @Override
    @RpcService
    public void refreshResult(PatientSearchRuleRequest request) throws ControllerException {
        if (CommonUtils.isEmpty(request.getPatientSearchRuleId())) {
            throw new ControllerException("检索规则id不可为空");
        }
        //刷新暂时不控制是否订阅，直接刷新
        this.ruleExecute(request.getPatientSearchRuleId(), ExecutionModeEnum.SUBSCRIBE.getModeCode(), null);
    }

    /**
     * 获取科室负责人
     */
    @Override
    @RpcService
    public List<DeptLeaderListRepHisBean.DeptLeaderHisBean> queryDeptLeaderList(DoctorListByMemQo qo) throws ControllerException {
        if (CommonUtils.isEmpty(qo.getDeptId())) {
            return new ArrayList<>();
        }
        DeptLeaderListRequest request =  new DeptLeaderListRequest();
        request.setDeptCode(qo.getDeptId());
        request.setDoctorName(qo.getDoctorName());
        DeptLeaderListRepHisBean deptLeaderListRepHisBean = patientHisService.queryDeptLeaderList(request);
        List<DeptLeaderListRepHisBean.DeptLeaderHisBean> leaderList = deptLeaderListRepHisBean.getLeaderList();
        /*List<Doctor> doctorList = new ArrayList<>();
        for (DeptLeaderListRepHisBean.DeptLeaderHisBean deptLeader : leaderList) {
            Doctor doctor = doctorInfoServiceIntf.getDoctorByOrgAndLocalDoctorId(qo.getOrgId(), deptLeader.getDoctorCode());
            if(doctor==null){
                log.warn("医生不存在，orgId={}，doctorCode={}", qo.getOrgId(), deptLeader.getDoctorCode());
                continue;
            }
            doctorList.add(doctor);
        }*/
        return leaderList;
    }

    /**
     * 查询检索或订阅的患者列表
     *
     * @param request
     * @return org.atag.core.base.BaseResponse<specialist.bean.response.QueryPatientSearchResultResponse>
     * @throws
     * @author tongtp
     * @date 2021/8/11 11:32
     */
    @Override
    @RpcService
    public QueryPatientSearchResultResponse queryPatientSearchResult(PatientSearchRuleRequest request) throws ControllerException {
        log.info( "queryPatientSearchResult 入参:" + JSONObject.toJSONString(request));
        if (CommonUtils.isEmpty(request.getPatientSearchRuleId())) {
            throw new ControllerException("搜索规则不可为空");
        }
        if (CommonUtils.isEmpty(request.getExecutionMode())) {
            throw new ControllerException("执行方式不可为空");
        }
        Long total = patientSearchResultDAO.getPatientSearchResultCount(request);
        QueryPatientSearchResultResponse patientSearchResultResponse = new QueryPatientSearchResultResponse();
        patientSearchResultResponse.setTotal(total);
        if (total > 0) {
            List<PatientSearchResult> patientSearchResults = patientSearchResultDAO.queryPatientSearchResult(request);
            log.info( "queryPatientSearchResult 查询数据:" + JSONObject.toJSONString(patientSearchResults));
            if (!CollectionUtils.isEmpty(patientSearchResults)) {
                List<PatientSearchResultListVo> list = new ArrayList<>();
                for (PatientSearchResult patientSearchResult : patientSearchResults) {
                    PatientSearchResultListVo vo = new PatientSearchResultListVo();
                    vo.setOrganizationId(patientSearchResult.getOrganizationId());
                    vo.setSearchTime(patientSearchResult.getSearchTime());
                    vo.setStatus(patientSearchResult.getStatus());
                    vo.setPatientNumberType(patientSearchResult.getPatientNumberType());
                    vo.setPatientNumber(patientSearchResult.getPatientNumber());
                    vo.setPersonId(patientSearchResult.getPersonId());
                    vo.setPatientId(patientSearchResult.getPatientId());
                    vo.setPatientName(patientSearchResult.getPatientName());
                    vo.setPatientSex(patientSearchResult.getPatientSex());
                    vo.setPatientBirthday(patientSearchResult.getPatientBirthday());
                    vo.setPatientTelephone(patientSearchResult.getPatientMobile());
                    vo.setPatientMedicalCardType(patientSearchResult.getPatientMedicalCardType());
                    vo.setPatientMedicalCardNumber(patientSearchResult.getPatientMedicalCardNumber());
                    vo.setCardType(patientSearchResult.getPatientIdentityCardType());
                    vo.setCardNumber(patientSearchResult.getPatientIdentityCardNumber());
                    vo.setPatientAge(patientSearchResult.getPatientAge());
                    vo.setChronicDiseaseIds(patientSearchResult.getChronicDiseaseIds());
                    vo.setChronicDiseaseName(patientSearchResult.getChronicDiseaseName());
                    list.add(vo);
                }
                patientSearchResultResponse.setList(list);
            }
        }
        log.info( "queryPatientSearchResult 出参:" + JSONObject.toJSONString(patientSearchResultResponse));
        //该规则所有未读的更新为已读的
        patientSearchResultDAO.updateStatus(request.getPatientSearchRuleId());
        return patientSearchResultResponse;
    }

    /**
     * 规则执行
     *
     * @param patientSearchRuleId
     * @param executionMode
     * @return base.BaseResponse
     * @throws
     * @author tongtp
     * @date 2021/8/6 15:44
     */
    private void ruleExecute(Long patientSearchRuleId, final Byte executionMode, List<PatientSearchRuleDetail> patientSearchRuleDetails) throws ControllerException {
        //查询规则
        PatientSearchRule patientSearchRule = patientSearchRuleDAO.get(patientSearchRuleId);
        if (CommonUtils.isEmpty(patientSearchRuleDetails)) {
            //查询规则详情
            patientSearchRuleDetails = patientSearchRuleDetailDAO.queryByPatientSearchRuleId(patientSearchRuleId);
            if (CommonUtils.isNotEmpty(patientSearchRuleDetails)) {
                patientSearchRuleDetails.stream().map(patientSearchRuleDetail -> {
                    if (RuleConditionTypeEnum.OUTPATIENT_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()
                            || RuleConditionTypeEnum.IN_HOSPITAL_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()
                            || RuleConditionTypeEnum.OUT_HOSPITAL_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()) {
                        patientSearchRuleDetail.setDiagnosisList(Arrays.asList(patientSearchRuleDetail.getFirstConditionName().split(",")));

                    }
                    return patientSearchRuleDetail;
                }).collect(Collectors.toList());
            }

        }
        //记录时间的条件是会影响其他所有条件的,先遍历一轮找出记录时间
        Date recordStartTime = null;
        Date recordEndTime = null;
        for (PatientSearchRuleDetail patientSearchRuleDetail : patientSearchRuleDetails) {
            if (RECORD_TIME.getType().equals(patientSearchRuleDetail.getRuleConditionType())) {
                recordStartTime = patientSearchRuleDetail.getStartDate();
                recordEndTime = patientSearchRuleDetail.getEndDate();
                break;
            }
            if (RuleConditionTypeEnum.OUTPATIENT_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()
                    || RuleConditionTypeEnum.IN_HOSPITAL_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()
                    || RuleConditionTypeEnum.OUT_HOSPITAL_DIAGNOSIS.getType() == patientSearchRuleDetail.getRuleConditionType()) {
                patientSearchRuleDetail.setDiagnosisList(Arrays.asList(patientSearchRuleDetail.getFirstConditionName().split(",")));
            }
        }
        //目前的规则是记录时间必填的，所以如果没有就直接结束
        if (recordStartTime == null || recordEndTime == null) {
            throw new ControllerException("记录时间为空,规则无法继续执行");
        }
        //遍历规则的所有条件依次执行筛选:
        //and相连的规则检索出来的数据求交集，遇到OR连接符时，把前面检索出来的数据集合保存，
        //后面检索出来的数据在遇到下一个OR连接符或者结束时与前面检索出来的数据集合求并集
        List<PatientSearchProcess> previousList = new ArrayList<>();
        List<PatientSearchProcess> currentList = new ArrayList<>();
        long start = System.currentTimeMillis();
        boolean currentInit = false;
        for (int i = 0; i < patientSearchRuleDetails.size(); i++) {
            PatientSearchRuleDetail patientSearchRuleDetail = patientSearchRuleDetails.get(i);
            if (!RECORD_TIME.getType().equals(patientSearchRuleDetail.getRuleConditionType())) {
                if (RuleLineTypeEnum.AND.getType().equals(patientSearchRuleDetail.getRuleLineType())) {
                    List<PatientSearchProcess> tempList = searchByCondition(patientSearchRuleDetail,
                            recordStartTime, recordEndTime);
                    if (!currentInit) {
                        currentList.addAll(tempList);
                        currentInit = true;
                    } else {
                        //求交集
                        currentList.retainAll(tempList);
                    }
                } else if (RuleLineTypeEnum.OR.getType().equals(patientSearchRuleDetail.getRuleLineType())) {
                    //currentList合并到数据集合previousList中
                    previousList.addAll(currentList);
                    currentList.clear();
                    currentList.addAll(searchByCondition(patientSearchRuleDetail, recordStartTime,
                            recordEndTime));
                }
            }
            if (i == patientSearchRuleDetails.size() - 1) {
                previousList.addAll(currentList);
            }
        }
        if (!CollectionUtils.isEmpty(previousList)) {
            //去重
            HashSet<PatientSearchProcess> h = new HashSet(previousList);
            previousList.clear();
            previousList.addAll(h);
        }
        log.info("patientSearchRuleId:{},executionMode:{},共筛选出患者信息:{}条,检索总耗时:{}ms", patientSearchRuleId,
                executionMode, previousList.size(), System.currentTimeMillis() - start);
        log.info("patientSearchRuleId:{},executionMode:{},共筛选出患者信息:{}条,数据详情:{}", patientSearchRuleId,
                executionMode, previousList.size(), previousList);
        //根据筛选出的结果集调用接口查询出完整的患者信息
        if (!CollectionUtils.isEmpty(previousList)) {
            //执行方式：1 订阅 2 手动检索
            //执行方式为1的，库内相同规则且执行方式为1的已有该患者信息的则不在保存
            //执行方式为2的，先清除相同规则且执行方式为2的所有患者信息然后在依次保存
            if (ExecutionModeEnum.SEARCH.getModeCode().equals(executionMode)) {
                patientSearchResultDAO.deleteByPatientSearchRuleId(patientSearchRuleId);
            }
            //标准版直接保存检索结果
            start = System.currentTimeMillis();
            List<QueryPatientInfoResponse.PatientInfo> patientInfoList = transformPatientInfo(previousList);
            log.info("patientSearchRuleId:{},executionMode:{},数据转换总耗时:{}ms", patientSearchRuleId,
                    executionMode, previousList.size(), System.currentTimeMillis() - start);
            start = System.currentTimeMillis();
            for (PatientSearchProcess patientInfo :
                    previousList) {
                QueryPatientInfoResponse.PatientInfo info = transformPatientInfo(patientInfo);
                if (ExecutionModeEnum.SEARCH.getModeCode().equals(executionMode)) {
                    saveResultRecord(patientSearchRuleId, executionMode, info);
                } else {
                    savePatientSearchResult(patientSearchRuleId, executionMode, info);
                }
            }
            log.info("patientSearchRuleId:{},executionMode:{},保存数据总耗时:{}ms", patientSearchRuleId,
                    executionMode, previousList.size(), System.currentTimeMillis() - start);
        }
        //更新规则的最后执行时间
        patientSearchRule.setLastExecutionTime(new Date());
        patientSearchRuleDAO.update(patientSearchRule);
        return;
    }

    /**
     * 保存PatientSearchResult
     *
     * @param patientSearchRuleId
     * @param executionMode
     * @param patientInfo
     * @return void
     * @throws
     * @author tongtp
     * @date 2021/8/10 21:09
     */
    private void savePatientSearchResult(Long patientSearchRuleId, Byte executionMode,
                                         QueryPatientInfoResponse.PatientInfo patientInfo) {
        //查询相同规则相同执行方式的患者已存在则不再保存
        Long patientByCount = patientSearchResultDAO.getPatientByCount(patientInfo, patientSearchRuleId,
                executionMode);
        if (patientByCount > 0) {
            //log.info("患者已存在，不再保存patientInfo:{},patientSearchRuleId:{},executionMode:{}", patientInfo,
            // patientSearchRuleId, executionMode);
            //患者已存在。则更新
            PatientSearchResult patientSearchResult =
                    patientSearchResultDAO.queryPatientSearchResultByPerson(patientInfo, patientSearchRuleId,
                            executionMode);
            patientSearchResult.setExecutionMode(executionMode);
            patientSearchResult.setChronicDiseaseIds(patientInfo.getChronicDiseaseIds());
            patientSearchResult.setChronicDiseaseName(patientInfo.getChronicDiseaseName());
            patientSearchResultDAO.update(patientSearchResult);
        } else {
            saveResultRecord(patientSearchRuleId, executionMode, patientInfo);
        }
    }

    /**
     * 保存结果记录
     *
     * @param patientSearchRuleId
     * @param executionMode
     * @param patientInfo
     * @return void
     * @throws
     * @author tongtp
     * @date 2022/8/10 14:33
     */
    private void saveResultRecord(Long patientSearchRuleId, Byte executionMode,
                                  QueryPatientInfoResponse.PatientInfo patientInfo) {
        PatientSearchResult patientSearchResult = new PatientSearchResult();
        patientSearchResult.setPatientSearchRuleId(patientSearchRuleId);
        patientSearchResult.setOrganizationId(patientInfo.getOrganizationId());
        patientSearchResult.setSearchTime(new Date());
        patientSearchResult.setStatus(ReadStatusEnum.UNREAD.getStatus());
        patientSearchResult.setPatientNumberType(CommonUtils.isEmpty(patientInfo.getPatientNumberType()) == true ?
                (byte) 1 : patientInfo.getPatientNumberType());
        patientSearchResult.setPatientNumber(patientInfo.getPatientNumber());
        patientSearchResult.setPatientId(patientInfo.getPatientId());
        patientSearchResult.setPatientIdentityCardType(patientInfo.getCardType());
        patientSearchResult.setPatientIdentityCardNumber(patientInfo.getCardNumber());
//			patientSearchResult.setPatientMedicalCardType(patientInfo.getPatientMedicalCardType());
//			patientSearchResult.setPatientMedicalCardNumber(patientInfo.getPatientMedicalCardNumber());
        patientSearchResult.setPatientName(patientInfo.getPatientName());
        patientSearchResult.setPersonId(patientInfo.getPersonId());
        patientSearchResult.setPatientSex(Byte.valueOf(patientInfo.getPatientSex()));
        patientSearchResult.setPatientAge(patientInfo.getPatientAge());
        patientSearchResult.setPatientBirthday(patientInfo.getPatientBirthday());
        patientSearchResult.setPatientMobile(patientInfo.getPatientMobile());
        patientSearchResult.setExecutionMode(executionMode);
        patientSearchResult.setChronicDiseaseIds(patientInfo.getChronicDiseaseIds());
        patientSearchResult.setChronicDiseaseName(patientInfo.getChronicDiseaseName());
        patientSearchResultDAO.save(patientSearchResult);
    }

    /**
     * 处理保存到检索结果表入参-单实体
     *
     * @param patient
     * @return
     */
    private QueryPatientInfoResponse.PatientInfo transformPatientInfo(PatientSearchProcess patient) {
        QueryPatientInfoResponse.PatientInfo patientInfo = new QueryPatientInfoResponse.PatientInfo();
        patientInfo.setPatientNumberType(patient.getSource());
        patientInfo.setOrganizationId(patient.getOrganizationId());
        patientInfo.setPatientNumber(patient.getPatientNumber());
        patientInfo.setPatientId(patient.getPatientId());
        patientInfo.setPatientName(patient.getPatientName());
        patientInfo.setPatientAge(patient.getPatientAge());
        patientInfo.setPatientSex(patient.getPatientSex());
        patientInfo.setPatientMobile(patient.getTelephone());
        patientInfo.setCardType(patient.getCardType());
        patientInfo.setCardNumber(patient.getCardNumber());
        patientInfo.setChronicDiseaseIds(patient.getChronicDiseaseIds());
        patientInfo.setChronicDiseaseName(patient.getChronicDiseaseName());
        String mpiId = null;
        if (CommonUtils.isNotEmpty(patient.getOrganizationId())) {
            Organization orgDetailByOrgCode = organizationRpcService.getOrgDetailByOrgCode(patient.getOrganizationId());
            if (CommonUtils.isNotEmpty(orgDetailByOrgCode)) {
                mpiId = pcnIdentityServiceImpl.findMpiIdByPatientCode(orgDetailByOrgCode.getOrgId(),
                        patient.getPatientId());
            }
        }
        if (CommonUtils.isEmpty(mpiId)) {
            patientInfo.setPatientMobile(null);
            patientInfo.setPersonId(patient.getPatientId());
        } else {
            patientInfo.setPersonId(mpiId);
            MpiDemographicinfo demographicinfo = pcnIdentityServiceImpl.getDemographicinfo(mpiId);
            if (CommonUtils.isNotEmpty(demographicinfo) && CommonUtils.isNotEmpty(demographicinfo.getPhoneNo())) {
                patientInfo.setPatientMobile(demographicinfo.getPhoneNo());
            }
        }
        return patientInfo;
    }

    /**
     * 处理保存到检索结果表入参
     *
     * @param previousList
     * @return
     */
    private List<QueryPatientInfoResponse.PatientInfo> transformPatientInfo(List<PatientSearchProcess> previousList) {
        List<QueryPatientInfoResponse.PatientInfo> patientInfoList = new ArrayList<>();
        for (PatientSearchProcess patient : previousList) {
            patientInfoList.add(transformPatientInfo(patient));
        }
        return patientInfoList;
    }

//    /**
//     * 从HIS查询患者信息
//     *
//     * @param patientSearchRuleId
//     * @param executionMode
//     * @param outpatientNumberList
//     * @param queryType
//     * @return void
//     * @throws
//     * @author tongtp
//     * @date 2021/8/12 15:12
//     */
//    private void queryPatientInfoFromHIS(Long patientSearchRuleId, Byte executionMode,
//                                         List<String> outpatientNumberList,
//                                         Integer queryType) {
//        //HIS那边使用的Oracle数据库，in超过1000会抛异常
//        int pageSize = 900;
//        //重试次数
//        int retryCount = 0;
//        QueryPatientInfoRequest request = new QueryPatientInfoRequest();
//        request.setOrganizationId(Constants.DEFAULT_ORGANIZATION_ID);
//        request.setQueryType(queryType);
//        request.setPageSize(pageSize);
//        for (int i = 0; i < outpatientNumberList.size(); ) {
//            //每个查询条件集合到HIS都从第一页开始查询
//            int pageNo = 1;
//            if (outpatientNumberList.size() < i + pageSize) {
//                request.setQueryList(outpatientNumberList.subList(i, outpatientNumberList.size()));
//            } else {
//                request.setQueryList(outpatientNumberList.subList(i, i + pageSize));
//            }
//            i += pageSize;
//            //因为HIS查询出来的患者信息条数可能会超过传入的查询条件集合，所以需要遍历去查询
//            for (; ; ) {
//                request.setPageNo(pageNo);
//                List<QueryPatientInfoResponse.PatientInfo> tempList = null;
//                BaseResponse<QueryPatientInfoResponse> patientInfoBaseResponse =
//                        patientHisService.queryPatientInfoList(request);
//                log.info("patientHisService.queryPatientInfoList:request:{},BaseResponse:{}",
//                        request, patientInfoBaseResponse);
//                if (ResultCode.SUCCESS == patientInfoBaseResponse.getCode()) {
//                    QueryPatientInfoResponse data = patientInfoBaseResponse.getData();
//                    if (data != null) {
//                        tempList = data.getPatientInfoList();
//                    }
//                    if (CollectionUtils.isEmpty(tempList)) {
//                        //当前页为空则跳出循环
//                        break;
//                    }
//                    //成功了把重试次数置0
//                    retryCount = 0;
//                } else {
//                    retryCount++;
//                }
//                if (!CollectionUtils.isEmpty(tempList)) {
//                    for (QueryPatientInfoResponse.PatientInfo temp :
//                            tempList) {
//                        temp.setPatientNumberType(queryType.byteValue());
//                        //保存检索的患者信息
//                        savePatientSearchResult(patientSearchRuleId, executionMode, temp);
//                    }
//                }
//                if (retryCount > 3) {
//                    //错误次数连续超过3次则跳出循环
//                    break;
//                }
//                pageNo++;
//            }
//        }
//
//    }

    /**
     * 根据条件查询患者信息
     *
     * @param patientSearchRuleDetail
     * @param recordStartTime
     * @param recordEndTime
     * @return java.util.List<specialist.bean.response.PatientSearchProcess>
     * @throws
     * @author tongtp
     * @date 2021/8/18 15:22
     */
    private List<PatientSearchProcess> searchByCondition(PatientSearchRuleDetail patientSearchRuleDetail,
                                                         Date recordStartTime,
                                                         Date recordEndTime) {
        //  规则条件类型：1 记录时间 2 门诊病历 3 实验室报告 4 影像学报告 5 病理学报告 6 临床检查 7
        //  手术名称 8 非手术治疗 9 入院记录 10 护理医嘱 11 出院小结' 20 门诊诊断 21 入院诊断 22 出院诊断,
        List<PatientSearchProcess> result = new ArrayList<>();
        //如果不传条件筛选类型，直接返回空数组
        if (CommonUtils.isEmpty(patientSearchRuleDetail.getRuleLineType())) {
            return result;
        }
        Byte ruleConditionType = patientSearchRuleDetail.getRuleConditionType();
        //条件筛选方法：1 范围(包含边界) 2 等于 3 大于 4 小于 5 大于等于 6 小于等于，7包含，8不包含 9 Between
        Byte conditionFilterMethod = patientSearchRuleDetail.getConditionFilterMethod();

        SearchDocumentRequest request = new SearchDocumentRequest();
        request.setStartTime(DateUtil.dateFormate(recordStartTime, "yyyy-MM-dd HH:mm:ss"));
        request.setEndTime(DateUtil.dateFormate(recordEndTime, "yyyy-MM-dd HH:mm:ss"));
        request.setKeywords(patientSearchRuleDetail.getFirstKeywordContent());

        switch (getEnumByKey(ruleConditionType)) {
            //实验室报告
            case LABORATORY_REPORT:
                //先判断必填的条件是否为空，为空则返回空List
                if (CommonUtils.isNull(patientSearchRuleDetail.getSecondConditionCode()) || CommonUtils.isNull(conditionFilterMethod)
                        || CommonUtils.isNull(patientSearchRuleDetail.getFirstKeywordContent())) {
                    return result;
                }
                if (ConditionFilterMethodEnum.SCOPE.getType().equals(conditionFilterMethod)
                        && CommonUtils.isNull(patientSearchRuleDetail.getSecondKeywordContent())) {
                    return result;
                }
                //未定义的筛选方法，也返回空List
                if (ConditionFilterMethodEnum.getEnumByKey(conditionFilterMethod) == null) {
                    return result;
                }
                return inspectReportRecordDAO.queryPatientByInspectReportRecord(patientSearchRuleDetail, recordStartTime, recordEndTime);
            case OUTPATIENT_MEDICAL_RECORD:
                // 门诊病例
                request.setDocumentType("5200");
                return doSearchDocument(request);
            case IMAGE_REPORT:
                // 影像学报告
                request.setDocumentType("5410");
                //先判断必填的条件是否为空，为空则返回空List
                if (CommonUtils.isNull(patientSearchRuleDetail.getFirstConditionCode()) || CommonUtils.isNull(patientSearchRuleDetail.getSecondConditionCode())) {
                    return result;
                }
                //return doSearchDocument(request);
                return examReportDAO.queryPatientByExamReport(patientSearchRuleDetail, recordStartTime, recordEndTime);
            case PATHOLOGY_REPORT:
                // 病理学报告
                break;
            case SIGN_INFO:
                // 体征信息
                break;
            case CLINICAL_EXAMINATION:
                // 临床检查
                break;
            case OPERATIVE_NAME:
                if (CommonUtils.isNull(patientSearchRuleDetail.getFirstConditionCode())) {
                    return result;
                }
                // 手术名称
                return vrSurgicalRecordDAO.queryPatientBySurgicalRecord(patientSearchRuleDetail, recordStartTime,
                        recordEndTime);
            case NONOPERATIVE_TREATMENT:
                // 非手术治疗
                if (CommonUtils.isNull(patientSearchRuleDetail.getFirstConditionCode())) {
                    return result;
                }
                return treatmentRecordDAO.queryPatientByTreatmentRecord(patientSearchRuleDetail, recordStartTime, recordEndTime);
            case ADMISSION_RECORD:
                // 入院记录
                request.setDocumentType("6101");
                return doSearchDocument(request);
            case NURSING_ADVICE:
                // 护理医嘱
                request.setDocumentType("6301");
                return doSearchDocument(request);
            case DISCHARGE_SUMMARY:
                // 出院小结
                request.setDocumentType("6400");
                return doSearchDocument(request);
            case OUTPATIENT_DIAGNOSIS:
                //门诊诊断
                if (CommonUtils.isNull(patientSearchRuleDetail.getDiagnosisList())) {
                    return result;
                }
                return vrOutpatientVisitRecordDAO.queryOutpatientDiagnosisRecord(patientSearchRuleDetail, recordStartTime, recordEndTime);
            case IN_HOSPITAL_DIAGNOSIS:
                //入院诊断
                if (CommonUtils.isNull(patientSearchRuleDetail.getDiagnosisList())) {
                    return result;
                }
                return vrInpatientVisitRecordDAO.queryInOrOutHospitalDiagnosisRecord(patientSearchRuleDetail, recordStartTime, recordEndTime);
            case OUT_HOSPITAL_DIAGNOSIS:
                //出院诊断
                if (CommonUtils.isNull(patientSearchRuleDetail.getDiagnosisList())) {
                    return result;
                }
                return vrInpatientVisitRecordDAO.queryInOrOutHospitalDiagnosisRecord(patientSearchRuleDetail, recordStartTime, recordEndTime);
            default:
                return result;
        }
        return result;
    }


    /**
     * 5300 门（急）诊处方
     * 6001 住院病案首页
     * 5410 检查报告记录
     * 6101 入院记录
     * 5502 一般手术记录
     * 6200 住院病程记录
     * 5900 知情告知信息
     * 5401 检验报告记录
     * 5200 门（急）诊病历
     * 6400 住院小结
     * 5101 患者基本信息
     * 6301 住院医嘱
     *
     * @return list
     */
    private List<PatientSearchProcess> doSearchDocument(SearchDocumentRequest request) {


        List<PatientSearchProcess> result = new ArrayList<>();

        BaseResponse<SearchDocumentResponse> response = patientHisService.querySearchDocument(request);

        if (CommonUtils.isNotEmpty(response) && response.getCode() == ResultCode.SUCCESS) {
            SearchDocumentResponse dataResponse = response.getData();
            if (CommonUtils.isNotEmpty(dataResponse) && CommonUtils.isNotEmpty(dataResponse.getTotal()) && dataResponse.getTotal() > 0) {
                for (SearchDocumentList searchDocumentList : dataResponse.getList()) {

                    if (CommonUtils.isEmpty(searchDocumentList.getCardNumber()) &&
                            CommonUtils.isEmpty(searchDocumentList.getPatientId()) &&
                            CommonUtils.isEmpty(searchDocumentList.getPatientNumber())) {
                        continue;
                    }

                    PatientSearchProcess process = new PatientSearchProcess();
                    process.setCardNumber(searchDocumentList.getCardNumber());
                    process.setCardType(searchDocumentList.getCardType());
                    process.setPatientId(searchDocumentList.getPatientId());
                    process.setPatientNumber(searchDocumentList.getPatientNumber());
                    // OV门诊  iv住院
                    process.setSource((byte) ("OV".equals(searchDocumentList.getPatientNumberType()) ? 1 : 2));

                    result.add(process);
                }
            }

        }

        return result;
    }


    /*自动给患者发送当天院后随访需要健康宣教消息的定时任务*/
    @Override
    @RpcService
    public void autoHandleHospitalHealthEducationForSubscribe() throws ControllerException {
        String today = DateUtils.format(new Date(), DateUtils.DATE_FORMAT_10);
        List<FusAfterHosRecord> afterHosRecords = fusAfterHosRecordDAO.querySetSmsList(today);
        if (CommonUtils.isNotEmpty(afterHosRecords)) {
            for (FusAfterHosRecord afterHosRecord : afterHosRecords) {
                PushMessageBean pushMessageBean = new PushMessageBean();
                pushMessageBean.setPatientIdentityCardType(afterHosRecord.getCardType());
                pushMessageBean.setPatientIdentityCardNumber(afterHosRecord.getCardNumber());
                pushMessageBean.setPatientCode(afterHosRecord.getPatientId());
                pushMessageBean.setRoleId("patient");
                pushMessageBean.setTenantId(afterHosRecord.getTenantId());
                pushMessageBean.setTemplateCode(MsgTemplateCode.HOSPITAL_HEALTH_EDUCATION_NOTICE.getCode());
                pushMessageBean.setNotificateType(String.valueOf(NotificationEvent.NotificateType.hospital_health_education_notice));
                //对应消息变量map
                Map<String, String> variableMap = new HashMap<>();
                //APP消息跳转用
                variableMap.put("#姓名#", afterHosRecord.getPatientName());
                variableMap.put("#出院日期/门诊日期#", DateUtils.format(afterHosRecord.getVisitTime(),
                        DateUtils.DATE_FORMAT_10));
                variableMap.put("#SetTime#", DateUtils.format(afterHosRecord.getVisitTime(),
                        DateUtils.DATE_FORMAT_10) + " 09:00");
                variableMap.put("#OrgName#", afterHosRecord.getOrganizationName());
                variableMap.put("#DoctorName#", "系统自动发送");
                variableMap.put("#PatientName#", afterHosRecord.getPatientName());
                variableMap.put("#cardType#", afterHosRecord.getCardType());
                variableMap.put("#cardNumber#", afterHosRecord.getCardNumber());
                List<FusAfterHealthEducation> healthEducations =
                        fusAfterHealthEducationDAO.queryHealthEducationByRecordId(afterHosRecord.getRecordId());
                if (CommonUtils.isNotEmpty(healthEducations)) {
                    StringBuilder healthEducationsName = new StringBuilder();
                    List<Long> educationIdList = new ArrayList<>();
                    for (FusAfterHealthEducation healthEducation : healthEducations) {
                        healthEducationsName.append(healthEducation.getEducationName());
                        educationIdList.add(healthEducation.getEducationId());
                    }
                    variableMap.put("#HealthEducationsName#", healthEducationsName.toString());
                    variableMap.put("educationIdList", JSON.toJSONString(educationIdList));
                    pushMessageBean.setMsgVariableMap(variableMap);
                }
                Map<String, String> extras = new HashMap<>();
                extras.put("cardType", afterHosRecord.getCardType());
                extras.put("cardNumber", afterHosRecord.getCardNumber());
                pushMessageBean.setExtras(extras);
                try {
                    sendMsgService.productionMessage(pushMessageBean);
                } catch (Exception e) {
                    log.error("推送消息异常:", e);
                }
            }

        }

    }

}
